﻿//DdeColumnsComboBox.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Quik.Xaml
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Windows;

	using Ecng.Collections;
	using Ecng.Common;

	using Xceed.Wpf.Toolkit;

	///<summary>
	/// Выпадающий список для выбора набора столбцов DDE таблицы.
	///</summary>
	public class DdeColumnsComboBox : CheckComboBox
	{
		private List<RefPair<string, string>> _columns;
		private readonly SynchronizedList<RefPair<string, string>> _selectedColumns;
		private Type _ddeColumns;

		/// <summary>
		/// Список идентификаторов выбранных таблиц.
		/// </summary>
		public static readonly DependencyProperty SelectedColumnsProperty = DependencyProperty.Register("SelectedColumns", typeof(List<string>),
			typeof(DdeColumnsComboBox), new UIPropertyMetadata(new List<string>(), IsSelectedTableIdsChanged));

		private static void IsSelectedTableIdsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var ctrl = d as DdeColumnsComboBox;
			if (ctrl == null)
				return;

			var list = (List<string>)e.NewValue;

			if (list.Count == 0)
				list.AddRange(ctrl._selectedColumns.Select(t => t.First));
			else
				ctrl.SelectColumnsById(list.ToList());

			ctrl.UpdateText();
		}

		/// <summary>
		/// Список выбранных столбцов.
		/// </summary>
		public List<string> SelectedColumns
		{
			get { return (List<string>)GetValue(SelectedColumnsProperty); }
			set { SetValue(SelectedColumnsProperty, value); }
		}

		/// <summary>
		/// Столбцы, исключенные из списка выбора.
		/// </summary>
		public SynchronizedList<string> ExcludeColumns { get; private set; }

		/// <summary>
		/// Тип таблицы для редактирования списка столбцов.
		/// </summary>
		public Type DdeColumns
		{
			get { return _ddeColumns; }
			protected set
			{
				_ddeColumns = value;

				_columns = _ddeColumns
					.GetProperties()
					.Where(prop => !ExcludeColumns.Contains(prop.Name))
					.Select(propertyInfo => new RefPair<string, string>
					{
						First = propertyInfo.Name,
						Second = propertyInfo.GetValue(_ddeColumns, null).ToString(),
					})
					.ToList();

				ItemsSource = _columns;
			}
		}

		/// <summary>
		/// Создать <see cref="DdeColumnsComboBox"/>.
		/// </summary>
		public DdeColumnsComboBox()
		{
			DisplayMemberPath = "Second";
			ValueMemberPath = "First";

			ExcludeColumns = new SynchronizedList<string>();

			_selectedColumns = new SynchronizedList<RefPair<string, string>>();
			_selectedColumns.Added += value =>
			{
				if (!SelectedColumns.IsNull())
					SelectedColumns.Add(value.First);
			};
			_selectedColumns.Removed += value =>
			{
				if (!SelectedColumns.IsNull())
					SelectedColumns.Remove(value.First);
			};
			_selectedColumns.Cleared += () =>
			{
				if (!SelectedColumns.IsNull())
					SelectedColumns.Clear();
			};

			SelectedItemsOverride = _selectedColumns;
		}

		/// <summary>
		/// Метод, который вызывается при изменении выбранного значения.
		/// </summary>
		/// <param name="oldValue">Старое значение.</param>
		/// <param name="newValue">Новое значение.</param>
		protected override void OnSelectedValueChanged(string oldValue, string newValue)
		{
			base.OnSelectedValueChanged(oldValue, newValue);
			UpdateText();
		}

		private void UpdateText()
		{
			Text = "Выбрано: " + (SelectedColumns != null ? SelectedColumns.Count : 0);
		}

		/// <summary>
		/// Выделить столбцы в списке.
		/// </summary>
		/// <param name="columns">Список столбцов для выделения.</param>
		public void SelectColumns(IEnumerable<DdeTableColumn> columns)
		{
			if(columns.IsNull())
				throw new ArgumentNullException("columns");

			SelectColumns(columns.Select(c => c.Name));
		}

		private void SelectColumns(IEnumerable<string> columns)
		{
			if (!SelectedColumns.IsNull())
				SelectedColumns.Clear();

			_selectedColumns.Clear();
			_selectedColumns.AddRange(_columns.Where(t => columns.Contains(t.Second)));

			UpdateText();
		}

		private void SelectColumnsById(IEnumerable<string> columns)
		{
			if (!SelectedColumns.IsNull())
				SelectedColumns.Clear();

			_selectedColumns.Clear();
			_selectedColumns.AddRange(_columns.Where(t => columns.Contains(t.First)));

			UpdateText();
		}

		/// <summary>
		/// Получить список выбранных столбцов.
		/// </summary>
		/// <returns>Список столбцов.</returns>
		public IEnumerable<DdeTableColumn> GetSelectedColumns()
		{
			return DdeColumns.GetColumns(SelectedColumns);
		}
	}

	/// <summary>
	/// Выпадающий список для выбора набора столбцов таблицы Инструменты.
	/// </summary>
	public class DdeSecurityColumnsComboBox : DdeColumnsComboBox
	{
		/// <summary>
		/// Создать <see cref="DdeSecurityColumnsComboBox"/>.
		/// </summary>
		public DdeSecurityColumnsComboBox()
		{
			ExcludeColumns.AddRange(new[]
			{
				"Name",
				"Code",
				"Class",
				"Status",
				"MinLotSize",
				"MinStepSize",
			});
			DdeColumns = typeof(DdeSecurityColumns);
		}
	}
}
